/* Programme calculant la somme des éléments d'un tableau par une
   méthode de divide and conquer utilisant la bibliotheque thread*/

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "thread.h"


struct arg
{
  int * T;
  int d;
  int f;
  int somme;
};


int *init_table(int t)
{
  srand(time(NULL));
  int i;
  int * Tab = malloc(sizeof(int)*t);
  for (i=0 ; i<t ; i++)
    {
      Tab[i] = rand()%100;
    }
  return Tab;
}


static void * divide(void * A)
{
  struct arg * B = (struct arg *) A;
  if (B->d==B->f)
    {
      B->somme = B->T[B->d];
      thread_exit(B);
    }
  else
    {
      struct arg * A1= malloc(sizeof(struct arg));
      A1->T = B->T;
      A1->d = B->d;
      A1->f = (B->d+B->f)/2;

      struct arg * A2 = malloc(sizeof(struct arg));;
      A2->T = B->T;
      A2->d = (B->d+B->f)/2+1;
      A2->f = B->f;
      
      thread_t threadA1;
      thread_t threadA2;
          
      struct arg * Ar1;
      thread_create(&threadA1,divide,(void *)A1);
     
      struct arg * Ar2;
      thread_create(&threadA2,divide,(void *)A2);
      
      thread_join(&threadA1,(void **)&Ar1);
      
      
      thread_join(&threadA2,(void **)&Ar2);
      
      
      B->somme = Ar2->somme + Ar1->somme;
      free(A1);
      free(A2);
      thread_exit(B);
    }
}

int main(int argc, char* argv[])
{
  int i;
  struct arg * res;
  if(argc!=2)
  {
  	printf("entrez la taille en argument");
  	return 0;
  }
  
  
  int taille = atoi(argv[1]);
  int * T = init_table(taille);
  /*fprintf(stderr,"Tableau :\n");
  for (i=0;i<taille;i++)
    {
      fprintf(stderr,"%d  ",T[i]);
    }
  fprintf(stderr,"\n");
  */
  //initialisation des arguments
  struct arg * A =  malloc(sizeof(struct arg));
  A->T=T;
  A->d=0;
  A->f=taille-1;

  double debut,fin;
  debut =clock();
  thread_t thread1;
  thread_create(&thread1,divide,(void *)A);
  thread_join(&thread1,(void *)&res);
  fin = clock();
  printf("%d ",taille);
  free(A);
  free(T);
  fprintf(stdout,"%f\n",(double) (fin-debut)/(double)CLOCKS_PER_SEC);
  return 1;
}
